package cn.orangeframe.neon.domain.entity;

import cn.orangeframe.neon.domain.enums.TaskType;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;

import java.util.*;

@Data
public class WorkflowTask {

    @NotEmpty(message = "任务定义name不可为空")
    private String name;
    // 任务引用名称
    private String taskReferenceName;
    // 任务描述
    private String description;
    // 任务输入参数
    private Map<String, Object> inputParameters = new HashMap<>();
    // 任务类型，默认HTTP类型
    private String type = TaskType.HTTP.name();
    // 决策值参数名
    private String caseValueParam;
    // 决策表达式
    private String caseExpression;
    // 表达式
    private String expression;
    // 连接符
    private List<String> joinOn = new LinkedList<>();
    // 决策表
    private Map<String,@Valid List<@Valid WorkflowTask>> decisionCases = new LinkedHashMap<>();
    // 默认情况
    private List<@Valid WorkflowTask> defaultCase = new LinkedList<>();
    // 分支任务
    private List<@Valid List<@Valid WorkflowTask>> forkTasks = new LinkedList<>();
    // 循环任务
    private List<WorkflowTask> loopOver = new LinkedList<>();
    // 循环条件
    private String loopCondition;
    // 评估器类型
    private String evaluatorType = "javascript";
    // 是否可选
    private boolean optional = false;
    // 是否异步完成
    private Boolean asyncComplete = false;
    // 重试次数
    private int retryCount = 0;

    /**
     * 根据任务名获取下一个任务
     * @param taskReferenceName 任务名
     * @return 下一个任务
     */
    public WorkflowTask next(String taskReferenceName, WorkflowTask parent) {
        TaskType taskType = TaskType.valueOf(type);
        switch (taskType) {
            case DO_WHILE:
            case SWITCH:
                for (List<WorkflowTask> workflowTasks : children()) {
                    Iterator<WorkflowTask> iterator = workflowTasks.iterator();
                    while (iterator.hasNext()) {
                        WorkflowTask task = iterator.next();
                        if (task.getTaskReferenceName().equals(taskReferenceName)) {
                            break;
                        }
                        WorkflowTask nextTask = task.next(taskReferenceName, this);
                        if (nextTask != null) {
                            return nextTask;
                        }
                        if (task.has(taskReferenceName)) {
                            break;
                        }
                    }
                    if (iterator.hasNext()) {
                        return iterator.next();
                    }
                }
                break;
            case FORK:
                boolean found = false;
                for (List<WorkflowTask> workflowTasks : children()) {
                    Iterator<WorkflowTask> iterator = workflowTasks.iterator();
                    while (iterator.hasNext()) {
                        WorkflowTask task = iterator.next();
                        if (task.getTaskReferenceName().equals(taskReferenceName)) {
                            found = true;
                            break;
                        }
                        WorkflowTask nextTask = task.next(taskReferenceName, this);
                        if (nextTask != null) {
                            return nextTask;
                        }
                        if (task.has(taskReferenceName)) {
                            break;
                        }
                    }
                    if (iterator.hasNext()) {
                        return iterator.next();
                    }
                    if (found && parent != null) {
                        return parent.next(this.taskReferenceName, parent);
                    }
                }
                break;
            default:
                break;

        }
        return null;
    }

    /**
     * 根据当前任务类型获取子任务<br/>
     * 1、决策类型任务，返回所有决策分支任务和默认任务，即if()..else if()..else() <br/>
     * 2、并行任务，返回并行任务列表 <br/>
     * 3、循环任务，返回循环任务列表 <br/>
     * 其他任务类型返回空集合 <br/>
     * @return 子任务集合
     */
    private Collection<List<WorkflowTask>> children() {
        Collection<List<WorkflowTask>> workflowTaskLists = new LinkedList<>();
        TaskType taskType = TaskType.valueOf(type);

        switch (taskType) {
            case SWITCH:
                workflowTaskLists.addAll(decisionCases.values());
                workflowTaskLists.add(defaultCase);
                break;
            case FORK:
                workflowTaskLists.addAll(forkTasks);
                break;
            case DO_WHILE:
                workflowTaskLists.add(loopOver);
                break;
            default:
                break;
        }
        return workflowTaskLists;
    }

    /**
     * 递归收集所有任务
     * @return 所有任务集合
     */
    public List<WorkflowTask> collectTasks() {
        List<WorkflowTask> tasks = new LinkedList<>();
        tasks.add(this);
        for (List<WorkflowTask> workflowTaskList : children()) {
            for (WorkflowTask workflowTask : workflowTaskList) {
                tasks.addAll(workflowTask.collectTasks());
            }
        }
        return tasks;
    }

    /**
     * 判断当前任务是否包含名字为taskReferenceName的任务 <br/>
     * 目前仅有决策任务、循环任务、分支任务包含有子任务 <br/>
     * {@link #children()} 方法按任务类型返回对应的子任务集合，循环子任务集合并根据传入任务名判断是否包含
     * @param taskReferenceName 任务名
     * @return 是否包含
     */
    public boolean has(String taskReferenceName) {
        if (this.getTaskReferenceName().equals(taskReferenceName)) {
            return true;
        }
        TaskType taskType = TaskType.valueOf(type);

        switch (taskType) {
            case SWITCH:
            case DO_WHILE:
            case FORK:
                for (List<WorkflowTask> childx : children()) {
                    for (WorkflowTask child : childx) {
                        if (child.has(taskReferenceName)) {
                            return true;
                        }
                    }
                }
                break;
            default:
                break;
        }
        return false;
    }
}

